﻿using Examination.Args;
using Examination.Args.Request;
using Examination.Filter;
using Examination.Model;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace Examination.Controllers
{
    [Route("api/[controller]/[action]")]
    [ApiController]
    [TypeFilter(typeof(WebVerificationAdminFilterAttribute))]
    public class QuestionController : ControllerBase
    {
        private readonly DataContext _dataContext;

        public QuestionController(DataContext dataContext) => _dataContext = dataContext;

        [HttpPost]
        public async Task<IActionResult> Search([FromBody] ListParameter parameter)
        {
            if (string.IsNullOrEmpty(parameter.Key))
            {
                var questions = await _dataContext.Questions.Join(_dataContext.Users, q => q.CreatorId, u => u.Id, (q, u) => new { q.Id, q.CreateTime, q.Title, q.Type, q.Answer, q.Option1, q.Option2, q.Option3, q.Option4, creator = u.Name }).OrderByDescending(u => u.CreateTime).Skip(parameter.Page * parameter.Size).Take(parameter.Size).ToListAsync();
                long total = await _dataContext.Questions.Join(_dataContext.Users, q => q.CreatorId, u => u.Id, (q, u) => q.Id).CountAsync();
                long all = await _dataContext.Questions.CountAsync();
                long judge = await _dataContext.Questions.CountAsync(q => q.Type == QuestionType.Judge);
                long fill = await _dataContext.Questions.CountAsync(q => q.Type == QuestionType.Fill);
                long radio = await _dataContext.Questions.CountAsync(q => q.Type == QuestionType.Radio);
                long multiple = await _dataContext.Questions.CountAsync(q => q.Type == QuestionType.Multiple);
                return new JsonResult(new ResponseData() { Data = new { all, questions, judge, fill, radio, multiple, total } });
            }
            else
            {
                var questions = await _dataContext.Questions.Join(_dataContext.Users, q => q.CreatorId, u => u.Id, (q, u) => new { q.Id, q.CreateTime, q.Title, q.Type, q.Answer, q.Option1, q.Option2, q.Option3, q.Option4, creator = u.Name, typeStr = q.Type == QuestionType.Judge ? "判断题" : (q.Type == QuestionType.Radio ? "单选题" : (q.Type == QuestionType.Multiple ? "多选题" : "填空题")) }).Where(q => q.Title.Contains(parameter.Key) || q.creator.Contains(parameter.Key) || q.typeStr.Contains(parameter.Key)).OrderByDescending(u => u.CreateTime).Skip(parameter.Page * parameter.Size).Take(parameter.Size).ToListAsync();
                long total = await _dataContext.Questions.Join(_dataContext.Users, q => q.CreatorId, u => u.Id, (q, u) => new { q.Id, q.CreateTime, q.Title, creator = u.Name, typeStr = q.Type == QuestionType.Judge ? "判断题" : (q.Type == QuestionType.Radio ? "单选题" : (q.Type == QuestionType.Multiple ? "多选题" : "填空题")) }).CountAsync(q => q.Title.Contains(parameter.Key) || q.creator.Contains(parameter.Key) || q.typeStr.Contains(parameter.Key));
                long all = await _dataContext.Questions.CountAsync();
                long judge = await _dataContext.Questions.CountAsync(q => q.Type == QuestionType.Judge);
                long fill = await _dataContext.Questions.CountAsync(q => q.Type == QuestionType.Fill);
                long radio = await _dataContext.Questions.CountAsync(q => q.Type == QuestionType.Radio);
                long multiple = await _dataContext.Questions.CountAsync(q => q.Type == QuestionType.Multiple);
                return new JsonResult(new ResponseData() { Data = new { all, questions, judge, fill, radio, multiple, total } });
            }
        }

        [HttpPost]
        public async Task<IActionResult> Add([FromBody] AddQuestionParameter parameter, [FromServices] IArgsExtend argsExtend)
        {
            User user = ((ArgsExtend)argsExtend).User;
            Question question = new Question()
            {
                CreatorId = user.Id,
                Type = parameter.Type,
                Title = parameter.Title,
                Answer = parameter.Answer,
                Option1 = parameter.Option1,
                Option2 = parameter.Option2,
                Option3 = parameter.Option3,
                Option4 = parameter.Option4
            };
            await _dataContext.Questions.AddAsync(question);
            await _dataContext.SaveChangesAsync();
            return new JsonResult(new ResponseData() { Data = question });
        }

        [HttpPost]
        public async Task<IActionResult> Update([FromBody] UpdateQuestionParameter parameter, [FromServices] IArgsExtend argsExtend)
        {
            User user = ((ArgsExtend)argsExtend).User;
            Question question = await _dataContext.Questions.FirstOrDefaultAsync(q => q.Id == parameter.Id);
            if (question == null)
            {
                return new JsonResult(new ResponseData() { Status = 1, Msg = "题不存在" });
            }
            else
            {
                question.CreatorId = user.Id;
                question.Title = parameter.Title;
                question.Answer = parameter.Answer;
                question.Option1 = parameter.Option1;
                question.Option2 = parameter.Option2;
                question.Option3 = parameter.Option3;
                question.Option4 = parameter.Option4;
            }
            _dataContext.Questions.Update(question);
            await _dataContext.SaveChangesAsync();
            return new JsonResult(new ResponseData() { Data = question });
        }

        [HttpPost]
        public async Task<IActionResult> Delete([FromQuery] int id)
        {
            Question question = await _dataContext.Questions.FirstOrDefaultAsync(q => q.Id == id);
            if (question == null)
            {
                return new JsonResult(new ResponseData() { Status = 1, Msg = "删除失败，题目不存在" });
            }
            if (await _dataContext.ExamQuestions.CountAsync(e => e.QuestionId == question.Id) > 0)
            {
                return new JsonResult(new ResponseData() { Status = 1, Msg = "删除失败，该题已在比赛中使用，请尝试先删除比赛" });
            }
            _dataContext.Questions.Remove(question);
            await _dataContext.SaveChangesAsync();
            return new JsonResult(new ResponseData());
        }

        [HttpPost]
        public IActionResult RegularTest([FromBody] RegularTestParameter parameter)
        {
            Regex regex = new Regex(parameter.RegularExpression, parameter.Case ? RegexOptions.None : RegexOptions.IgnoreCase);
            return new JsonResult(new ResponseData() { Data = new { result = regex.IsMatch(parameter.TestText) } });
        }
    }
}
